package com.cuoyi.coupon.mall.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.cuoyi.coupon.mall.common.BusinessException;
import com.cuoyi.coupon.mall.config.SessionLocal;
import com.cuoyi.coupon.mall.constant.BusinessConstant;
import com.cuoyi.coupon.mall.enums.ErrorEnum;
import com.cuoyi.coupon.mall.model.dto.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * @author chengzhang
 * 2021/11/11 16:52
 */
@Slf4j
public class JWTUtils {

    public static String createToken(String username, Integer expireSeconds) {
        Map<String, String> mapClaim = new HashMap<>();
        mapClaim.put(BusinessConstant.LOGIN_USER_ID_KEY, username);
        return createToken(mapClaim, expireSeconds);
    }

    private static String createToken(Map<String, String> map, Integer expireSeconds) {
        String token = null;
        Map<String, Object> mapHeader = new HashMap<>();
        mapHeader.put("alg", "HS256");
        mapHeader.put("typ", "JWT");
        JWTCreator.Builder jwtBuilder = JWT.create();
        jwtBuilder.withHeader(mapHeader);

        if (map != null && !map.isEmpty()) {
            Set<Map.Entry<String, String>> setEntry = map.entrySet();
            for (Map.Entry<String, String> entry : setEntry) {
                jwtBuilder.withClaim(entry.getKey(), entry.getValue());
            }
        }

        Calendar nowTime = Calendar.getInstance();
        int calendarField = Calendar.SECOND;
        nowTime.add(calendarField, expireSeconds);
        Date expiresDate = nowTime.getTime();
        jwtBuilder.withExpiresAt(expiresDate);
        jwtBuilder.withIssuedAt(new Date());
        try {
            token = jwtBuilder.sign(Algorithm.HMAC256(BusinessConstant.ALGORITHM_HMAC256));
        } catch (Exception e) {
            log.error("hippoLogin createToken error", e);
        }
        return token;
    }

    public static String getValue(String token, String key) {
        Map<String, Claim> claims = getClaims(token);
        if (claims == null) {
            return null;
        }
        Claim valueClaim = claims.get(key);
        if (null == valueClaim || valueClaim.asString().equals("")) {
            return null;
        }
        return valueClaim.asString();
    }

    public static Map<String, Claim> getClaims(String token) {
        DecodedJWT jwt = verifyToken(token);
        return jwt == null ? null : jwt.getClaims();
    }

    public static DecodedJWT verifyToken(String token) {
        DecodedJWT jwt = null;
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(BusinessConstant.ALGORITHM_HMAC256)).build();
            jwt = verifier.verify(token);
        } catch (Exception e) {
            log.error("verifyToken error", e);
        }
        return jwt;
    }

    public static String getUserName(String userName) {
        if (StringUtils.isNotEmpty(userName)) {
            return userName;
        }
        UserDTO user = SessionLocal.getUser();
        if (Objects.nonNull(user)) {
            return user.getUserName();
        }
        throw new BusinessException(ErrorEnum.PARAMS_ERROR.code(), "用户令牌token无效，请重新登录!");
    }

    public static String getUserName() {
        UserDTO user = SessionLocal.getUser();
        if (Objects.nonNull(user)) {
            return user.getUserName();
        }
        return "";
    }
}
